package lol.clann.minecraft.springboot.plugin.bukkit.impl;

import com.mojang.authlib.GameProfile;
import com.ruoshui.utils.java.reflect.ReflectUtils;
import com.ruoshui.utils.java.reflect.model.FieldFilter;
import io.netty.channel.Channel;
import lol.clann.minecraft.springboot.api.annotation.compatibility.CompatibilityChecked;
import lol.clann.minecraft.springboot.api.bukkit.utils.*;
import lol.clann.minecraft.springboot.api.model.reflect.FieldInvoker;
import lol.clann.minecraft.springboot.bukkit.utils.BukkitUtils;
import lol.clann.minecraft.springboot.bukkit.utils.NMSClasses;
import lombok.extern.slf4j.Slf4j;
import net.minecraft.server.v1_7_R4.*;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 *
 * @author pyz
 * @date 2019/5/2 5:28 PM
 */
@Slf4j
@Service
@CompatibilityChecked
public class PlayerUtilsImpl_all extends PlayerUtilsImpl {
    @Autowired
    private PacketUtils packetUtils;

    private FieldInvoker channel;

    @Autowired
    private PluginUtils pluginUtils;
    @Autowired
    private ServerUtils serverUtils;
    @Autowired
    private WorldUtils worldUtils;
    @Autowired
    private EntityUtils entityUtils;

    @Override
    @PostConstruct
    protected void init() throws NoSuchFieldException {
        super.init();
        channel = new FieldInvoker(ReflectUtils.getField(NMSClasses.getNetworkManager(), FieldFilter.create().setType(Channel.class)));
    }

    @Override
    public <T> void sendPacket(Player player, T packet) {
        PlayerConnection pc = getPlayerConnection(player);
        if (pc != null) {
            pc.sendPacket((Packet) packet);
        }
    }

    @Override
    public <T> T toNMS(Player player) {
        return (T) ((CraftPlayer) player).getHandle();
    }

    @Override
    public Player toBukkit(Object nmsPlayer) {
        return (Player) entityUtils.toBukkit(nmsPlayer);
    }

    @Override
    public <T> T getNetworkManager(Player player) {
        PlayerConnection pc = getPlayerConnection(player);
        return (T) pc.networkManager;
    }

    @Override
    public <T> T getPlayerConnection(Player player) {
        EntityPlayer ep = toNMS(player);
        return (T) ep.playerConnection;
    }

    @Override
    public Channel getChannel(Player player) {
        return (Channel) channel.get(getNetworkManager(player));
    }

    @Override
    public void sendPluginMessage(Player player, String channel, byte[] message) {
        sendPluginMessage(player, pluginUtils.getSelf(), channel, message);
    }

    /**
     * 因为某些原因,客户端和服务端玩家快捷栏位置可能不一样
     * 此方法能同步客户端的快捷栏位置
     *
     * @param player
     */
    @Override
    public void refreshHotbarIndex(Player player) {
        sendPacket(player, packetUtils.newPacketPlayOutHeldItemSlot(player.getInventory().getHeldItemSlot()));
    }

    /**
     * 同步指定位置的方块
     *
     * @param player
     * @param x
     * @param y
     * @param z
     */
    public void updateBlock(Player player, int x, int y, int z) {
        Object packet = packetUtils.newPacketPlayOutBlockChange(x, y, z, player.getWorld());
        sendPacket(player, packet);
    }

    /**
     * 将OfflinePlayer转换为Player
     *
     * @param p
     * @return
     */
    @Override
    public Player toOnlinePlayer(OfflinePlayer p) {
        if (p == null) {
            return null;
        }
        Player target = getOnlinePlayer(p.getName());
        if (target != null) {
            return target;
        }

        Object nmsServer = serverUtils.getNMSServer();
        Object nmsWorld = worldUtils.toNMS(Bukkit.getWorlds().get(0));
        Object itemInWorldManager;
        if (BukkitUtils.getBukkitVersionNumber() < 11400) {
            itemInWorldManager = new PlayerInteractManager((World) nmsWorld);
        } else {
            itemInWorldManager = new net.minecraft.server.v1_14_R1.PlayerInteractManager((net.minecraft.server.v1_14_R1.WorldServer) nmsWorld);
        }
        Object profile;
        Object nmsPlayer;
        profile = new GameProfile(p.getUniqueId(), p.getName());
        if (BukkitUtils.getBukkitVersionNumber() < 10800) {
            nmsPlayer = new EntityPlayer((MinecraftServer) nmsServer, (WorldServer) nmsWorld, (net.minecraft.util.com.mojang.authlib.GameProfile) profile, (PlayerInteractManager) itemInWorldManager);
        } else {
            nmsPlayer = new net.minecraft.server.v1_8_R3.EntityPlayer((net.minecraft.server.v1_8_R3.MinecraftServer) nmsServer, (net.minecraft.server.v1_8_R3.WorldServer) nmsWorld, (com.mojang.authlib.GameProfile) profile, (net.minecraft.server.v1_8_R3.PlayerInteractManager) itemInWorldManager);
        }
        target = toBukkit(nmsPlayer);
        if (target == null) {
            return null;
        }
        target.loadData();
        return target;
    }

}
